home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / lisp / eulisp / mpfeel.lha / MPFeel / system.c < prev    next >
C/C++ Source or Header  |  1992-10-06  |  14KB  |  681 lines

  1. /* ******************************************************************** */
  2. /* system.c          Copyright (C) Codemist and University of Bath 1989 */
  3. /*                                                                      */
  4. /* Environment specific code                                           */
  5. /* ******************************************************************** */
  6.  
  7. /*
  8.  * $Id: system.c,v 1.4 1992/02/10 12:01:10 pab Exp $
  9.  *
  10.  * $Log: system.c,v $
  11.  * Revision 1.4  1992/02/10  12:01:10  pab
  12.  * Gc on/off fixes
  13.  *
  14.  * Revision 1.3  1992/01/29  13:49:07  pab
  15.  * sysV fixes
  16.  *
  17.  * Revision 1.2  1991/09/11  12:07:46  pab
  18.  * 11/9/91 First Alpha release of modified system
  19.  *
  20.  * Revision 1.1  1991/08/12  16:50:06  pab
  21.  * Initial revision
  22.  *
  23.  * Revision 1.9  1991/05/16  11:29:26  pab
  24.  * 'C' garbage collector additions
  25.  *
  26.  * Revision 1.8  1991/05/15  20:09:53  kjp
  27.  * Tidied suignal handling.
  28.  *
  29.  * Revision 1.7  1991/04/02  16:42:03  kjp
  30.  * BSD signal support.
  31.  *
  32.  * Revision 1.6  1991/02/28  13:53:54  kjp
  33.  * Fixed semaphore interaction with GC and sysv signalling.
  34.  *
  35.  * Revision 1.5  1991/02/13  18:25:46  kjp
  36.  * Pass.
  37.  *
  38.  */
  39.  
  40. #define SCHEDBUG(x) 
  41.  
  42. /*
  43.  * Change Log:
  44.  *   Version 1, April 1990
  45.  */
  46.  
  47. /*
  48.  
  49.  * This file (and it's accompanying '.h') are intended to encapsulate all
  50.  * of the system specific requirements of FEEL. For each target system
  51.  * there must be a set of functions conforming to the requested 
  52.  * configuration (e.g. if threads are required, the thread operations
  53.  * must exist along with their defined types - otherwise, they may be
  54.  * omitted).
  55.  
  56.  * It is expected that this file may degenerate into hash-includes.
  57.  
  58.  */
  59.  
  60. #include <signal.h>
  61.  
  62. #include "funcalls.h"
  63. #include "defs.h"
  64. #include "structs.h"
  65. #include "global.h"
  66. #include "error.h"
  67. #include "state.h"
  68.  
  69. #include "allocate.h"
  70. #include "garbage.h"
  71. #include "threads.h"
  72.  
  73. /*
  74.  * Nasty signal hackery! 
  75.  */
  76.  
  77. #ifdef WITH_BSD_SIGNALS
  78. #define sighold(sig) sigmask(sig)
  79. #define sigset(sig,func) signal(sig,func)
  80. #define my_sigpause(sig) sigpause(0)
  81. #else
  82. #define my_sigpause(sig) sigpause(sig)
  83. #endif
  84.  
  85. /*
  86.  * For a system to run with threads, the following must be provided:
  87.  *
  88.  *   Types: 
  89.  *     SystemSemaphore 
  90.  *
  91.  *   Functions:
  92.  *
  93.  *     char* system_malloc(int)
  94.  *     char* system_static_malloc(int)
  95.  *
  96.  *     void system_allocate_semaphore(SystemSemaphore *)
  97.  *     void system_initialise_semaphore(SystemSemaphore *)
  98.  *     void system_open_semaphore(SystemSemaphore *)
  99.  *     void system_close_semaphore(SystemSemaphore *)
  100.  *
  101.  */
  102.  
  103. SYSTEM_THREAD_SPECIFIC_DECLARATION(int,system_scheduler_number);
  104.  
  105. int system_running_processors = 1; /* Unless initialised otherwise */
  106.  
  107. /*
  108.  * Stack checking...
  109.  */
  110.  
  111. #define THREAD_STACK_MARGIN (3*1024)
  112. #define THREAD_GC_STACK_MARGIN (512)
  113.  
  114. static SYSTEM_GLOBAL(int,system_control_c_flag);
  115.  
  116. /* C-c interrupt handler... */
  117.  
  118. static void system_reenter_toplevel(LispObject *stacktop, int sig)
  119. {
  120.   IGNORE(sig);
  121.   SYSTEM_GLOBAL_VALUE(system_control_c_flag) = FALSE;
  122.   CallError(stacktop,"User Interrupt!",nil,NONCONTINUABLE);
  123. }
  124.  
  125. static void system_control_catcher(int sig)
  126. {
  127.   IGNORE(sig);
  128.   if (SYSTEM_GLOBAL_VALUE(system_control_c_flag)) {
  129.     fprintf(stderr,"Go away and leave me alone!\n");
  130.     fflush(stderr);
  131.     signal(02,system_control_catcher); /* Reinstall */
  132.     return;
  133.   }
  134.   SYSTEM_GLOBAL_VALUE(system_control_c_flag) = TRUE;
  135.   signal(02,system_control_catcher); /* Reinstall */
  136. }
  137.  
  138. int system_stacks_ok_p(LispObject *stacktop, LispObject form)
  139. {
  140.   extern LispObject interpreter_thread;
  141.   int handle;
  142.  
  143.   if (SYSTEM_GLOBAL_VALUE(system_control_c_flag)) 
  144.     system_reenter_toplevel(stacktop,0);
  145.  
  146. /*
  147.   if (CURRENT_THREAD() != (LispObject) interpreter_thread) {
  148.     fprintf(stderr,"{%d%%}",
  149.         ((int) &handle - (int) STACK_BASE())*100
  150.           / CURRENT_THREAD()->THREAD.stack_size);
  151.     fflush(stderr);
  152.   }
  153. */
  154.  
  155. #ifndef MACHINE_ANY
  156.   if ((int) &handle - (int) (STACK_BASE()) < THREAD_STACK_MARGIN)
  157.     CallError(stacktop,"SYSTEM: C stack overflowing",form,NONCONTINUABLE);
  158. #endif
  159.  
  160.   if ((CURRENT_THREAD())->THREAD.gc_stack_size 
  161.       - (int) (GC_STACK_POINTER()-GC_STACK_BASE()) * sizeof(LispObject)
  162.       < THREAD_GC_STACK_MARGIN)
  163.     {
  164.       CallError(stacktop,"SYSTEM: GC stack overflowing",form,NONCONTINUABLE);
  165.     }
  166.   return(TRUE);
  167. }
  168.  
  169. /* ******************************************************************** */
  170. /*                            Any Machine                               */
  171. /* ******************************************************************** */
  172.  
  173. #ifdef MACHINE_ANY
  174. #ifndef CGC
  175. char *system_malloc(int n)
  176. {
  177.   char *sbrk(int);
  178.   char *addr;
  179.  
  180.   if ((addr = (char *) sbrk(n)) == (char *) -1) {
  181.     perror("INITERROR: unable to allocate enough memory from system\n");
  182.     system_lisp_exit(1);
  183.   }
  184.  
  185.   return(addr);
  186. }
  187.  
  188. char *system_static_malloc(int n)
  189. {
  190.   char *sbrk(int);
  191.   char *addr;
  192.  
  193.   if ((addr = (char *) sbrk(n)) == (char *) -1) {
  194.     perror("INITERROR: out of static memory\n");
  195.     system_lisp_exit(1);
  196.   }
  197.  
  198.   return(addr);
  199. }
  200. #endif
  201. void system_lisp_exit(int n) 
  202. {
  203.   exit(n);
  204. }
  205.  
  206. void system_abort(int sig)
  207. {
  208.   fprintf(stderr,"\n\nAborting feel on signal %d\n\n",sig);
  209.   exit(sig);
  210. }
  211.  
  212. void runtime_initialise_system() 
  213. {
  214.   system_scheduler_number = 0;
  215.  
  216. #ifdef CGC
  217.   gc_init();
  218. #endif
  219.  
  220. #ifdef TRAP_ALL
  221.   signal(15,system_abort); 
  222.   signal(11,system_abort);
  223.   signal(10,system_abort);
  224.   signal(02,system_control_catcher); 
  225. #endif
  226.  
  227.   SYSTEM_INITIALISE_GLOBAL(int,system_control_c_flag,FALSE);
  228. }
  229.  
  230. #endif
  231.  
  232. /* ******************************************************************** */
  233. /*                               BSD                                    */
  234. /* ******************************************************************** */
  235.  
  236. #ifdef MACHINE_BSD
  237.  
  238. /*
  239.  * Memory allocation... 
  240.  */
  241.  
  242. char *system_malloc(int n)
  243. {
  244.   char *sbrk(int);
  245.   char *addr;
  246.  
  247.   if ((addr = (char *) sbrk(n)) == (char *) -1) {
  248.     perror("INITERROR: unable to allocate enough memory from system\n");
  249.     system_lisp_exit(1);
  250.   }
  251.  
  252.   return(addr);
  253. }
  254.  
  255. #define STATIC_MALLOC_HUNK_SIZE (4096)
  256.  
  257. char *static_free_ptr;
  258. int static_free_count;
  259.  
  260. char *system_static_malloc(int n)
  261. {
  262.   char *val;
  263.  
  264.   n = n + (n%BYTE_ALIGNMENT == 0 ? n : (BYTE_ALIGNMENT-n%BYTE_ALIGNMENT)); 
  265.   /* Alignment.. */
  266.  
  267.   if (static_free_count < n) {
  268.     char *new;
  269.  
  270.     if ((new = system_malloc(STATIC_MALLOC_HUNK_SIZE)) == NULL) {
  271.       fprintf(stderr,"INIT ERR: out of static memory\n");
  272.       exit(1);
  273.     }
  274.  
  275.     static_free_ptr = new;
  276.     static_free_count = STATIC_MALLOC_HUNK_SIZE;
  277.   }
  278.  
  279.   val = static_free_ptr;
  280.   static_free_ptr = val + n;
  281.   static_free_count -= n;
  282.  
  283.   return(val);
  284. }
  285.  
  286. /*
  287.  * Semaphores... (in header - dummies)
  288.  */
  289.  
  290. /*
  291.  * Signal handling...
  292.  */
  293.  
  294. /* Bad news signal handler... */
  295.  
  296. void system_abort(int sig)
  297. {
  298.   fprintf(stderr,"\n\nAborting EuLisp on signal %d... ",sig);
  299.   fprintf(stderr,"done\n\n");
  300.  
  301.   exit(1);
  302. }
  303.  
  304. /*
  305.  * Init and cleanup... 
  306.  */
  307.  
  308. void system_lisp_exit(int n)
  309. {
  310.   exit(n);
  311. }
  312.  
  313. void system_sleep_until_kicked() {}
  314.  
  315. void system_kick_sleepers() {}
  316.  
  317. void system_register_process(int pid) {IGNORE(pid);}
  318.  
  319. void runtime_initialise_system() 
  320. {
  321.   signal(15,system_abort); /* Catch terminations */
  322. /*
  323.   signal(11,system_abort);
  324.   signal(10,system_abort);
  325. */
  326.   signal(02,system_control_catcher); /* C-c with any luck */
  327.  
  328.   system_scheduler_number = 0;
  329. #ifdef CGC
  330.    gc_init();
  331. #endif
  332.  
  333.  
  334.   SYSTEM_INITIALISE_GLOBAL(int,system_control_c_flag,FALSE);
  335. }
  336.  
  337. #endif
  338.  
  339. /* ******************************************************************** */
  340. /*                             System V                                 */
  341. /* ******************************************************************** */
  342.  
  343. #ifdef MACHINE_SYSTEMV
  344.  
  345. /*
  346.  * Memory allocation...
  347.  */
  348.  
  349. /* Of shared memory segments... */
  350.  
  351. #define MAX_SHARED_SEGMENTS 100
  352.  
  353. int shared_ids[MAX_SHARED_SEGMENTS];
  354. int shared_segment_count;
  355.  
  356. char *system_malloc(int n)
  357. {
  358.   int seg;
  359.   char *addr;
  360.  
  361.   if (shared_segment_count >= MAX_SHARED_SEGMENTS) {
  362.     fprintf(stderr,"Can't allocate shared segment\n");
  363.     system_lisp_exit(1);
  364.   }
  365.  
  366.   if ((seg = shmget(IPC_PRIVATE,n,511|IPC_CREAT)) < 0) {
  367.     perror("shmget\n");
  368.     system_lisp_exit(1);
  369.   }
  370.  
  371.   if ((int) (addr = shmat(seg,NULL,NULL)) == -1) {
  372.     perror("shmat\n");
  373.     system_lisp_exit(1);
  374.   }
  375.  
  376.   shared_ids[shared_segment_count] = seg;
  377.  
  378.   ++shared_segment_count;
  379.  
  380.   return(addr);
  381. }
  382.  
  383. /* Of static shared bits (assumes serial for now)... */
  384.  
  385. #define STATIC_MALLOC_HUNK_SIZE (4096)
  386.  
  387. char *static_free_ptr;
  388. int static_free_count;
  389.  
  390. char *system_static_malloc(int n)
  391. {
  392.   char *val;
  393.  
  394.   n = n + (n%BYTE_ALIGNMENT == 0 ? n : (BYTE_ALIGNMENT-n%BYTE_ALIGNMENT)); 
  395.   /* Alignment.. */
  396.  
  397.   if (static_free_count < n) {
  398.     char *new;
  399.  
  400.     if ((new = system_malloc(STATIC_MALLOC_HUNK_SIZE)) == NULL) {
  401.       fprintf(stderr,"INIT ERR: out of static memory\n");
  402.       system_lisp_exit(1);
  403.     }
  404.  
  405.     static_free_ptr = new;
  406.     static_free_count = STATIC_MALLOC_HUNK_SIZE;
  407.   }
  408.  
  409.   val = static_free_ptr;
  410.   static_free_ptr = val + n;
  411.   static_free_count -= n;
  412.  
  413.   return(val);
  414. }
  415.  
  416. /*
  417.  * Semaphores...
  418.  */
  419.  
  420. void system_initialise_semaphore(SystemSemaphore *ptr)
  421. {
  422.   *ptr = 1;
  423. }
  424.  
  425. void system_allocate_semaphore(SystemSemaphore *ptr)
  426. {
  427.   *ptr = 1;
  428. }
  429. /* SystemV Semaphores excluded */
  430.  
  431. #ifdef SEMAPHORES_SOFTWARE
  432.  
  433. #include "lamport.h"
  434.  
  435. LamportSemaphore system_semaphore;
  436.  
  437. void system_open_semaphore(LispObject *stacktop, SystemSemaphore *ptr)
  438. {
  439.   extern SYSTEM_GLOBAL(SystemSemaphore,GC_sem);
  440.   int mine_flag = FALSE;
  441.  
  442.  top:
  443.  
  444.   lamport_enter(system_semaphore,system_scheduler_number);
  445.  
  446.   if (*ptr == 1) {
  447.     *ptr = 0;
  448.     mine_flag = TRUE;
  449.   }
  450.  
  451.   lamport_exit(system_semaphore,system_scheduler_number);
  452.  
  453.   if (mine_flag) return;
  454.  
  455.   if (ptr != &SYSTEM_GLOBAL_VALUE(GC_sem))
  456.     while (*ptr != 1) GC_sync_test();
  457.   else
  458.     while (*ptr != 1);
  459.  
  460.   goto top;
  461. }
  462.  
  463. int system_maybe_open_semaphore(LispObject *stacktop,SystemSemaphore *ptr)
  464. {
  465.   int mine_flag = FALSE;
  466.  
  467.   lamport_enter(system_semaphore,system_scheduler_number);
  468.  
  469.   if (*ptr == 1) {
  470.     *ptr = 0;
  471.     mine_flag = TRUE;
  472.   }
  473.  
  474.   lamport_exit(system_semaphore,system_scheduler_number);
  475.  
  476.   GC_sync_test();
  477.  
  478.   return(mine_flag);
  479. }
  480.  
  481. #endif
  482.  
  483. void system_close_semaphore(SystemSemaphore *ptr)
  484. {
  485.   *ptr = 1;
  486. }
  487.  
  488. /*
  489.  * Signal handling...
  490.  */
  491.  
  492. static SYSTEM_GLOBAL_ARRAY1(int,system_pids,MAX_PROCESSORS);
  493.  
  494. /* Bad news, free up semaphores and shared memory... */
  495.  
  496. void system_abort(int sig)
  497. {
  498.   int i;
  499.  
  500.   fprintf(stderr,"\n\nAborting EuLisp on signal %d... ",sig);
  501.  
  502.   for (i=0;i<shared_segment_count;++i) {
  503.     (void) shmctl(shared_ids[i],IPC_RMID,NULL);
  504.   }
  505.  
  506.   (void) semctl(system_semaphore,NULL,IPC_RMID,NULL);
  507.  
  508.   /* Kill of other processes too */
  509.  
  510.   for (i=0; i<RUNNING_PROCESSORS(); ++i)
  511.     if (i != system_scheduler_number)
  512.       kill(SYSTEM_GLOBAL_ARRAY1_VALUE(system_pids,i),SIGQUIT);
  513.  
  514.   fprintf(stderr,"done\n\n");
  515.  
  516.   exit(1);
  517. }
  518.  
  519. /*
  520.  * Init and cleanup... 
  521.  */
  522.  
  523. void system_lisp_exit(int n)
  524. {
  525.   int i;
  526.  
  527.   for (i=0;i<shared_segment_count;++i) {
  528.     (void) shmctl(shared_ids[i],IPC_RMID,NULL);
  529.   }
  530.  
  531.   (void) semctl(system_semaphore,NULL,IPC_RMID,NULL);
  532.  
  533.   /* Kill of other processes too */
  534.  
  535.   for (i=0; i<RUNNING_PROCESSORS(); ++i)
  536.     if (i != system_scheduler_number)
  537.       kill(SYSTEM_GLOBAL_ARRAY1_VALUE(system_pids,i),SIGQUIT);
  538.  
  539.   exit(n);
  540. }
  541.  
  542. /*
  543.  * Signal fiddling...
  544.  */
  545.  
  546. #define KICK_SIGNAL (SIGUSR1)
  547.  
  548. void system_kick_pid(int pid)
  549. {
  550.   extern int kill(int,int);
  551.  
  552.   (void) kill(pid,KICK_SIGNAL);
  553. }
  554.  
  555. static void system_nout()
  556. {
  557.   sigset(KICK_SIGNAL,system_nout);
  558. }
  559.  
  560. void system_sleep_until_kicked()
  561. {
  562.   extern int sigpause(int);
  563.  
  564.   (void) my_sigpause(KICK_SIGNAL);
  565.   sighold(KICK_SIGNAL);
  566. /*
  567.   fprintf(stderr,"{W:%d}\n",system_scheduler_number); fflush(stderr);
  568. */
  569.   fflush(stderr);
  570. }
  571.  
  572. static void system_read_nout()
  573. {
  574.   sigset(KICK_SIGNAL,system_read_nout);
  575. /*  GC_sync_test();*/
  576. }
  577.  
  578. #include <errno.h>
  579.  
  580. int system_read(int fno,char *buf,int max)
  581. {
  582.   int error;
  583.  
  584.   (void) sigset(KICK_SIGNAL,system_read_nout);
  585.  
  586.   do {
  587.  
  588.     error = read(fno,buf,max);
  589.     if (error > 0) {
  590.  
  591.       sigset(KICK_SIGNAL,system_nout);
  592.       (void) sighold(KICK_SIGNAL);
  593.  
  594.       PROFILE(printf("PVAL:%x\n",PROFILE_TIME(system_local_timer)));
  595.       fflush(stdout);
  596.       return(error);
  597.     }
  598.  
  599.   } while (errno == EINTR);
  600.  
  601.   return(error);
  602. }
  603.  
  604. void system_kick_sleepers()
  605. {
  606.   int i;
  607.  
  608.   for (i=0; i<RUNNING_PROCESSORS(); ++i)
  609.     if (i != system_scheduler_number)
  610.       kill(SYSTEM_GLOBAL_ARRAY1_VALUE(system_pids,i),KICK_SIGNAL);
  611. }
  612.  
  613. DEF_PROFILE_TIMER(system_local_timer);
  614.  
  615. void system_register_process(int n)
  616. {
  617.   SYSTEM_GLOBAL_ARRAY1_VALUE(system_pids,n) = getpid();
  618.   sigset(KICK_SIGNAL,system_nout);
  619.   sighold(KICK_SIGNAL);
  620.  
  621.   INIT_PROFILE_TIMER(system_local_timer);
  622. }
  623.  
  624. void runtime_initialise_system()
  625. {
  626.  
  627. #ifdef SEMAPHORES_SYSTEMV
  628.  
  629.   if ((system_semaphore = semget(IPC_PRIVATE,1,511)) < 0) {
  630.     perror("INIT ERROR: can't get semaphore\n");
  631.     exit(1);
  632.   }
  633.   if (semctl(system_semaphore,0,SETVAL,1) < 0) {
  634.     perror("INIT ERROR: initialise semaphore\n");
  635.     exit(1);
  636.   }
  637.  
  638.   system_sem_handler_array[0][0].sem_num = 0;
  639.   system_sem_handler_array[0][0].sem_op = -1;
  640.   system_sem_handler_array[0][0].sem_flg = NULL;
  641.  
  642. #endif
  643.  
  644.   shared_segment_count = 0;
  645.  
  646.   static_free_ptr = NULL;
  647.   static_free_count = 0;
  648.  
  649.   /* Bad news signals */
  650.  
  651.   sigset(SIGTERM,system_abort); /* Catch terminations */
  652.   sigset(SIGQUIT,system_abort); /* Quits */
  653.   sigset(SIGSEGV,system_abort); /* Segmentation faults */
  654.   sigset(SIGBUS,system_abort);  /* Bus errors */
  655.  
  656.   /* Error trapped signals */
  657.  
  658.   sigset(SIGINT,system_control_catcher); /* C-c with any luck */
  659.  
  660.   /* Ignore kick signals until we need them */
  661.  
  662.   sighold(KICK_SIGNAL); 
  663.  
  664. #ifdef SEMAPHORES_SOFTWARE
  665.  
  666.   system_semaphore 
  667.     = (LamportSemaphore) 
  668.         system_static_malloc(sizeof(struct lamport_semaphore));
  669.   lamport_initialise(system_semaphore);
  670.  
  671.   SYSTEM_INITIALISE_GLOBAL_ARRAY1(int,system_pids,MAX_PROCESSORS,0);
  672.   SYSTEM_GLOBAL_ARRAY1_VALUE(system_pids,0) = getpid();
  673.  
  674. #endif
  675.  
  676.   SYSTEM_INITIALISE_GLOBAL(int,system_control_c_flag,FALSE);
  677. }
  678.  
  679. #endif
  680.  
  681.